package com.nineclock.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.dto.SysDepartmentDTO;
import com.nineclock.system.dto.SysRoleDTO;
import com.nineclock.system.excel.ExcelMember;
import com.nineclock.system.excel.ExcelMemberParserListener;
import com.nineclock.system.mapper.*;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SysCompanyUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Transactional
public class SysCompanyUserServiceImpl implements SysCompanyUserService {

    @Autowired
    private SysCompanyUserMapper companyUserMapper;
    @Autowired
    private SysRoleMapper roleMapper;

    @Override
    public List<SysCompanyUserDTO> queryCompanyUser(Long userId , Long companyId) {
        //校验参数
        if(userId == null && companyId == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //动态组装查询条件
        LambdaQueryWrapper<SysCompanyUser> companyUserWrapper = new LambdaQueryWrapper<>();
        if(companyId != null) {
            companyUserWrapper.eq(SysCompanyUser::getCompanyId, companyId);
        }
        if(userId != null) {
            companyUserWrapper.eq(SysCompanyUser::getUserId, userId);
        }

        //执行查询
        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(companyUserWrapper);

        //组装结果
        List<SysCompanyUserDTO> companyUserDTOS = BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
        if(CollectionUtil.isEmpty(companyUserDTOS)){
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }



        //-----------------------> 查询员工的角色信息 , 并封装

        //查询并封装每一个员工的角色信息
        companyUserDTOS.forEach(sysCompanyUserDTO -> {
            Long companyId1 = sysCompanyUserDTO.getCompanyId();
            Long userId1 = sysCompanyUserDTO.getUserId();

            List<SysRole> sysRoles = roleMapper.queryRoleByUserIdAndCompanyId(userId1, companyId1);
            List<SysRoleDTO> roleDTOS = BeanHelper.copyWithCollection(sysRoles, SysRoleDTO.class);

            sysCompanyUserDTO.setRoles(roleDTOS);
        });

        return companyUserDTOS;
    }


    @Override
    public SysCompanyUserDTO queryCurrentAdmin() {

        //获取当前企业ID
        Long companyId = CurrentUserHolder.get().getCompanyId();

        //查询当前企业的系统管理员
        SysCompanyUser companyUser = companyUserMapper.queryCurrentAdminByCompanyId(companyId);

        //封装数据并返回
        return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
    }


    @Override
    public List<SysCompanyUserDTO> queryCompanyMemberList() {
        //获取企业ID
        Long companyId = CurrentUserHolder.get().getCompanyId();

        //组装条件查询
        LambdaQueryWrapper<SysCompanyUser> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(SysCompanyUser::getCompanyId, companyId); //企业ID
        userWrapper.eq(SysCompanyUser::getEnable, (short)1);

        List<SysCompanyUser> companyUsers = companyUserMapper.selectList(userWrapper);

        //封装结果返回
        return BeanHelper.copyWithCollection(companyUsers, SysCompanyUserDTO.class);
    }


    @Override
    public SysCompanyUserDTO queryByCompanyUserId(Long companyUserId) {
        SysCompanyUser companyUser = companyUserMapper.selectById(companyUserId);
        return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
    }


    @Override
    public List<SysCompanyUserDTO> queryAllCompanyUser() {

        //获取企业ID
        Long companyId = CurrentUserHolder.get().getCompanyId();

        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, companyId);
        wrapper.eq(SysCompanyUser::getEnable, (short)1);

        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(wrapper);

        return BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
    }


    @Override
    public PageResult<SysCompanyUserDTO> queryMembers(Integer page, Integer pageSize, String keyword, Long departmentId) {
        //组装条件
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());

        //关键字
        if(StrUtil.isNotEmpty(keyword)){//姓名, 工号 , 手机号
            wrapper.eq(SysCompanyUser::getUserName,keyword)
                    .or()
                    .eq(SysCompanyUser::getWorkNumber, keyword)
                    .or()
                    .eq(SysCompanyUser::getMobile, keyword);
        }

        //部门ID
        // departmentId 可能是顶级部门, 也可能是子部门
        //获取当前 departmentId 及其它下面的所有的 子部门的ID 集合

        List<Long> depIds = new ArrayList<>();
        depIds.add(departmentId);

        //递归查询该部门ID下的所有的子部门ID ----> 封装到集合
        queryDepartmentIdsWithChildren(depIds, departmentId);

        wrapper.in(SysCompanyUser::getDepartmentId, depIds);


        //执行查询
        Page<SysCompanyUser> pageObj = new Page<>(page, pageSize); //组装分页条件
        pageObj = companyUserMapper.selectPage(pageObj , wrapper);

        List<SysCompanyUser> records = pageObj.getRecords();

        //封装结果
        if(CollectionUtil.isNotEmpty(records)){
            List<SysCompanyUserDTO> userDTOS = BeanHelper.copyWithCollection(records, SysCompanyUserDTO.class);

            //补充员工的所属部门
            userDTOS.stream().forEach(sysCompanyUserDTO -> {

                Long id = sysCompanyUserDTO.getDepartmentId();
                String name = sysCompanyUserDTO.getDepartmentName();

                SysDepartmentDTO department = new SysDepartmentDTO();
                department.setId(id);
                department.setName(name);

                //将department设置到sysCompanyUserDTO
                sysCompanyUserDTO.setDepartment(department);
            });

            return new PageResult<>(pageObj.getTotal(), pageObj.getPages(), userDTOS);
        }

        return null;
    }



    @Autowired
    private SysDepartmentMapper departmentMapper;

    /**
     * 递归查询指定部门ID下的所有的子部门信息
     * @param depIds
     * @param departmentId
     */
    private void queryDepartmentIdsWithChildren(List<Long> depIds, Long departmentId) { //10009

        LambdaQueryWrapper<SysDepartment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrapper.eq(SysDepartment::getParentId, departmentId); //10009

        List<SysDepartment> departments = departmentMapper.selectList(wrapper);
        if(CollectionUtil.isNotEmpty(departments)){
            departments.stream().forEach(sysDepartment -> {
                Long depId = sysDepartment.getId();
                depIds.add(depId);

                queryDepartmentIdsWithChildren(depIds, depId);
            });
        }

    }


    @Override
    public void parseExcel(MultipartFile excelFile) throws IOException {
        //校验参数
        if(excelFile == null){
            throw new NcException(ResponseEnum.UPLOAD_FILE_NOT_FOUND);
        }

        //解析Excel文件
        EasyExcel.read(excelFile.getInputStream(), ExcelMember.class, new ExcelMemberParserListener(this)).sheet(0).doRead();
    }


    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysCompanyUserRoleMapper userRoleMapper;

    @Override
    public void importData(List<ExcelMember> memberList) {
        if(CollectionUtil.isNotEmpty(memberList)){
            for (ExcelMember excelMember : memberList) {

                SysUser sysUser = new SysUser();
                //1. 插入用户数据 ---> sys_user
                //1.1 判定手机号 / 邮箱是否被占用
                Integer count = userMapper.countByMobileAndEmail(excelMember.getMobile(), excelMember.getEmail());
                if(count >= 1){
                    throw new NcException(ResponseEnum.USER_MOBILE_EMAIL_EXISTS);
                }

                //1.2 判定工号是否被占用
                Integer worknumCount = companyUserMapper.countByWorknum(excelMember.getWorkNumber());
                if(worknumCount >= 1){
                    throw new NcException(ResponseEnum.WROK_NUM_EXISTS);
                }

                //1.3 组装用户的基本信息
                sysUser.setMobile(excelMember.getMobile());
                sysUser.setEmail(excelMember.getEmail());
                sysUser.setUsername(excelMember.getName());
                sysUser.setCreateTime(excelMember.getEntryTime());

                sysUser.setStatus(excelMember.getEnable().equals("可用")?(short)1:(short)0);
                sysUser.setPassword(new BCryptPasswordEncoder().encode("123456"));
                sysUser.setLastLoginCompanyId(CurrentUserHolder.get().getCompanyId());

                //1.4 保存用户
                userMapper.insert(sysUser);



                //2. 插入员工数据 ---> sys_company_user -------> SysCompanyUser
                SysCompanyUser companyUser = new SysCompanyUser();
                //2.1 组装员工基本信息
                companyUser.setEnable(excelMember.getEnable().equals("可用")?(short)1:(short)0);
                companyUser.setUserId(sysUser.getId()); //用户ID
                companyUser.setUserName(excelMember.getName());
                companyUser.setMobile(excelMember.getMobile());
                companyUser.setEmail(excelMember.getEmail());
                companyUser.setRemark(excelMember.getDesc());
                companyUser.setPost(excelMember.getPosition());
                companyUser.setCompanyId(CurrentUserHolder.get().getCompanyId()); //企业ID
                companyUser.setCompanyName(CurrentUserHolder.get().getCompanyName());//企业名称
                companyUser.setOfficeAddress(excelMember.getWorkAddr());
                companyUser.setTimeEntry(excelMember.getEntryTime());
                companyUser.setWorkNumber(excelMember.getWorkNumber());


                //2.2 根据部门名称获取部门ID
                //根据部门名称查询部门信息
                String departmentName = excelMember.getDepartmentName();
                if(StrUtil.isNotEmpty(departmentName)){
                    companyUser.setDepartmentName(excelMember.getDepartmentName());

                    LambdaQueryWrapper<SysDepartment> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
                    wrapper.eq(SysDepartment::getName, departmentName);

                    SysDepartment department = departmentMapper.selectOne(wrapper);
                    if(department != null){
                        companyUser.setDepartmentId(department.getId());
                    }
                }

                //2.3 保存员工信息
                companyUserMapper.insert(companyUser);


                //2.4 保存员工-角色关联关系 --------> sys_company_user_role
                String roleName = excelMember.getRoleName();
                if(StrUtil.isNotEmpty(roleName)){
                    //根据角色名查询角色
                    LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(SysRole::getCompanyId, CurrentUserHolder.get().getCompanyId());
                    wrapper.eq(SysRole::getRoleDesc, roleName);

                    SysRole role = roleMapper.selectOne(wrapper);
                    if(role != null){

                        //组装SysCompanyUserRole
                        SysCompanyUserRole userRole = new SysCompanyUserRole();
                        userRole.setCompanyUserId(companyUser.getId());
                        userRole.setCompanyId(CurrentUserHolder.get().getCompanyId());
                        userRole.setRoleId(role.getId());

                        userRoleMapper.insert(userRole);
                    }
                }

            }
        }
    }


    @Override
    public SysCompanyUserDTO findCompanyUserByMobile(String mobile) {

        //校验
        if(StrUtil.isEmpty(mobile)){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //组装条件查询
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrapper.eq(SysCompanyUser::getMobile, mobile);

        SysCompanyUser companyUser = companyUserMapper.selectOne(wrapper);

        //组装返回
        return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
    }


    @Override
    public Integer queryUserCountByDepartmentIds(List<Long> departmentIds) {// 10009, 10010

        //校验参数
        if(CollectionUtil.isEmpty(departmentIds)){
            return 0;
        }

        //遍历部门集合, 获取每一个部门下的子部门ID -------> 集合
        List<Long> depIds = new ArrayList<>(); //存放所有的查询出来的部门ID集合
        depIds.addAll(departmentIds);

        for (Long depId : departmentIds) {
            queryDepartmentIdsWithChildren(depIds, depId);
        }

        //去重
        Set<Long> ids = new HashSet<>(depIds);

        //组装条件查询
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrapper.in(SysCompanyUser::getDepartmentId, ids);

        Integer count = companyUserMapper.selectCount(wrapper);
        return count;
    }


    @Override
    public String queryUserById(Long userId) {
        SysCompanyUser user = companyUserMapper.selectById(userId);
        String userName = user.getUserName();
        return userName;

    }

    @Override
    public SysCompanyUserDTO queryAdminByCompanyId(Long companyId) {
        SysCompanyUser companyUser = companyUserMapper.queryCurrentAdminByCompanyId(companyId);
        return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
    }

}
